package com.iceclean.serviceImpl;

import com.iceclean.dao.*;
import com.iceclean.daoImpl.*;
import com.iceclean.po.*;
import com.iceclean.service.PostService;
import com.iceclean.service.ResourceService;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : Ice'Clean
 * @date : 2021-05-04
 */
public class PostServiceImpl implements PostService {

    UserDao userDao = new UserDaoImpl();
    PostDao postDao = new PostDaoImpl();
    PostBarDao postBarDao = new PostBarDaoImpl();
    PostLikedDao postLikedDao = new PostLikedDaoImpl();
    PostCollectedDao postCollectedDao = new PostCollectedDaoImpl();
    PostBrowsingDao postBrowsingDao = new PostBrowsingDaoImpl();
    PostCommentDao postCommentDao = new PostCommentDaoImpl();
    ResourceService resourceService = new ResourceServiceImpl();

    @Override
    public Post findPostById(int postId) {
        return postDao.findPostById(postId);
    }

    @Override
    public List<Post> findPostsByPage(int postBarId, int page, int num, int postDelete, String sortClass, String sortWay) {
        return postDao.findPostsByPage(postBarId, page, num, postDelete, sortClass, sortWay);
    }

    @Override
    public List<Post> findUserPostsByPage(int userId, int page, int num) {
        return postDao.findUserPostsByPage(userId, page, num);
    }

    @Override
    public List<Post> searchPostByPage(int postBarId, String search, int page, int num, String sortClass, String sortWay) {
        return postDao.searchPostByPage(postBarId, search, page, num, sortClass, sortWay);
    }

    @Override
    public int getAllSearchForNumber(int postBarId, String search) {
        return postDao.getAllSearchForNumber(postBarId, search);
    }

    @Override
    public int getAllDeletePostForNumber(int postBarId) {
        return postDao.getAllDeletePostForNumber(postBarId);
    }

    /**
     * 先获取所有的历史浏览记录
     * 然后通过浏览记录得到每一个贴子，再返回
     * @param userId 所属用户
     * @param page 页数
     * @param num 每页的数目
     * @return 符合条件的贴子集合
     */
    @Override
    public List<Post> findBrowsingByPage(int userId, int page, int num) {
        // 得到浏览记录列表
        List<PostBrowsing> postBrowsingList = postBrowsingDao.findBrowsingByPage(userId, page, num);

        // 取出所有对应的贴子
        List<Post> postList = new ArrayList<>();
        for (PostBrowsing postBrowsing : postBrowsingList) {
            postList.add(postDao.findPostById(postBrowsing.getPostId()));
        }

        return postList.size() == 0 ? null : postList;
    }

    /**
     * 首先获取得到所有的收藏记录
     * 然后通过收藏记录得到每一个贴子，再返回
     * @param userId 指定用户的 id
     * @param page 页数
     * @param num 每页的数目
     * @return 符合条件的贴子集合
     */
    @Override
    public List<Post> findPostCollectedByPage(int userId, int page, int num) {
        // 得到收藏记录列表
        List<PostCollected> postCollectedList = postCollectedDao.findPostCollectedByPage(userId, page, num);

        // 取出所有对应的贴子
        List<Post> postList = new ArrayList<>();
        for (PostCollected postCollected : postCollectedList) {
            postList.add(postDao.findPostById(postCollected.getPostId()));
        }

        return postList.size() == 0 ? null : postList;
    }

    @Override
    public List<PostComment> findPostCommentByPage(int postId, int page, int num) {
        return postCommentDao.findPostCommentByPage(postId, page, num);
    }

    @Override
    public List<PostComment> findPostCommentByPage(int postId, int rootCommentId, int page, int num) {
        return postCommentDao.findPostCommentByPage(postId, rootCommentId, page, num);
    }

    @Override
    public int getNumberOfAllBrowsing(int userId) {
        return postBrowsingDao.getNumberOfAllBrowsing(userId);
    }

    @Override
    public int getNumberOfAllPostCollected(int userId) {
        return postCollectedDao.getNumberOfAllPostCollected(userId);
    }

    /**
     * 创建新贴子时
     * 需要将贴子对应贴吧的贴子数 +1，贴子对应用户的贴子数 +1
     * 如果有公告贴 id 的话，则设置（没有的话传入 -1）
     * @param postBarId 新贴子所属贴吧 id
     * @param userId 新贴子发布者 id
     * @param postName 新贴子标题
     * @param postContent 新贴子内容
     * @return 新贴子 id
     */
    @Override
    public int createPost(int postBarId, int userId, String postName, String postContent, int postAdminId) {
        // 获取贴子所属贴吧对象，并将贴子数 +1
        PostBar postBar = postBarDao.findPostBarById(postBarId);
        postBar.setPostNumber(postBar.getPostNumber() + 1);
        postBarDao.updatePostBar(postBar);

        // 获取贴子所属用户对象，并将贴子数 +1
        User user = userDao.findUserById(userId);
        user.setUserPostNumber(user.getUserPostNumber() + 1);
        userDao.updateUser(user);

        // 判断是否为公告贴
        if (postAdminId > 0) {
            return postDao.createPost(new Post(postBarId, userId, postName, postContent, postAdminId));
        } else {
            return postDao.createPost(new Post(postBarId, userId, postName, postContent));
        }
    }

    /**
     * 删除贴子只是将贴子的删除标识置为 1，让其无法被看见与搜索到
     * 吧主可以选择恢复被删除的贴子
     * 删除的同时应将贴子的创建者贴子数 -1，贴子所属贴吧贴子数 -1
     * @param postId 贴子 id
     * @return 是否删除成功
     */
    @Override
    public boolean deletePost(int postId) {
        // 获取对应贴子，并设置删除标识为 1
        Post post = postDao.findPostById(postId);
        post.setPostDelete(1);

        // 获取对应贴子的创建者，并将贴子数 -1
        User user = userDao.findUserById(post.getUserId());
        user.setUserPostNumber(user.getUserPostNumber() - 1);
        userDao.updateUser(user);

        // 获取贴子对应的贴吧，并将贴子数 -1
        PostBar postBar = postBarDao.findPostBarById(post.getPostBarId());
        postBar.setPostNumber(postBar.getPostNumber() - 1);
        postBarDao.updatePostBar(postBar);

        // 最后将更新贴子
        return postDao.updatePost(post);
    }

    @Override
    public boolean recoverPost(int postId) {
        // 获取对应贴子，并设置删除标识为 0
        Post post = postDao.findPostById(postId);
        post.setPostDelete(0);

        // 获取对应贴子的创建者，并将贴子数 +1
        User user = userDao.findUserById(post.getUserId());
        user.setUserPostNumber(user.getUserPostNumber() + 1);
        userDao.updateUser(user);

        // 获取贴子对应的贴吧，并将贴子数 +1
        PostBar postBar = postBarDao.findPostBarById(post.getPostBarId());
        postBar.setPostNumber(postBar.getPostNumber() + 1);
        postBarDao.updatePostBar(postBar);

        return postDao.updatePost(post);
    }

    /**
     * 这里没有写回复的根回复，则该回复本身为根回复
     * 在创建新根回复时，将对应贴子的回复数 +1，楼层数 +1
     * 而该根回复对应的楼层数为贴子更新后的楼层数
     * 记录下回复和楼层的总数，就不用每次都去数据库查看到底有多少条记录了
     * @param postId 新回复所属贴子 id
     * @param userId 新回复发布者 id
     * @param commentContent 新回复的内容
     * @return 新回复实例对象
     */
    @Override
    public PostComment createPostComment(int postId, int userId, String commentContent) {
        // 获取到对应的贴子，并将回复数和楼层数 +1
        Post post = postDao.findPostById(postId);
        post.setPostComment(post.getPostComment() + 1);
        post.setPostFloor(post.getPostFloor() + 1);
        postDao.updatePost(post);

        // 创建新的回复保存到数据库并返回实例对象
        int id = postCommentDao.createPostComment(new PostComment(postId, userId, commentContent, post.getPostFloor()));
        return postCommentDao.findPostCommentById(id);
    }

    /**
     * 这里传进来了根回复的 id，说明该回复为子回复
     * 在创建新子回复时，只将贴子的回复数 +1，而楼层数不变，同时要将该根回复的子回复数 +1
     * @param postId 新回复所属贴子 id
     * @param userId 新回复发布者 id
     * @param rootCommentId 新回复的根回复 id
     * @param commentContent 新回复的内容
     * @return 新回复实例对象
     */
    @Override
    public PostComment createPostComment(int postId, int userId, int rootCommentId, String commentContent) {
        // 获取到对应的贴子，并将回复数 +1
        Post post = postDao.findPostById(postId);
        post.setPostComment(post.getPostComment() + 1);
        postDao.updatePost(post);

        // 获取到对应的更回复，并将回复数 +1
        PostComment postComment = postCommentDao.findPostCommentById(rootCommentId);
        postComment.setCommentReply(postComment.getCommentReply() + 1);
        postCommentDao.updatePostComment(postComment);

        // 创建新的子回复保存到数据库并返回实例对象
        int id = postCommentDao.createPostComment(new PostComment(postId, userId, rootCommentId, commentContent));
        return postCommentDao.findPostCommentById(id);
    }

    /**
     * （1）如果该回复为根回复（即子回复数量大于 0 的），那要将其所有子回复也删除掉
     * 同时对应贴子的楼层数 -1，回复数 -1
     * （2）如果该回复为子回复，要将对应根回复的回复数 -1
     * 同时对应贴子的回复数 -1
     * @param postCommentId 贴子回复 id
     * @return 是否删除成功
     */
    @Override
    public boolean deletePostComment(int postCommentId) {
        // 获取到回复对象和对应的贴子对象
        PostComment postComment = postCommentDao.findPostCommentById(postCommentId);
        Post post = postDao.findPostById(postComment.getPostId());


        // 找到其所有的子评论并删除
        if (postComment.getRootCommentId() == null) {
            System.out.println(postComment.getCommentContent());
            // 是根评论的话，删除所有子回复
            List<PostComment> postCommentList = postCommentDao.findPostCommentByRoot(postCommentId);
            if (postCommentList != null) {
                for (PostComment temp : postCommentList) {
                    System.out.println("找到的回贴：" + postComment);
                    // 删除子回复，并将贴子回复数 -1
                    postCommentDao.deletePostComment(temp.getCommentId());
                    post.setPostComment(post.getPostComment() - 1);
                }
            }

            // 然后将贴子楼层数 -1
            post.setPostFloor(post.getPostFloor() - 1);
        } else {
            // 是子评论的话，要将对应根评论的回复数 -1
            PostComment rootPostComment = postCommentDao.findPostCommentById(postComment.getRootCommentId());
            rootPostComment.setCommentReply(rootPostComment.getCommentReply() - 1);
            postCommentDao.updatePostComment(rootPostComment);
        }

        // 再将回复数 -1，并更新贴子
        post.setPostComment(post.getPostComment() - 1);
        postDao.updatePost(post);

        // 最后删除回复本身（先删除回复所持有的资源，再删除回复本身）
        resourceService.deleteResourceByComment(postCommentId);
        return postCommentDao.deletePostComment(postCommentId);
    }

    /**
     * 对历史浏览记录的优化
     * 当用户进入一个贴子时，首先先判断是否有该贴子的历史浏览记录
     * 如果有，则删掉旧的浏览记录，再将新的浏览记录插入，可以避免浏览记录的冗余
     * @param postId 贴子 id
     * @param userId 用户 id
     * @return 历史浏览对象
     */
    @Override
    public PostBrowsing addPostBrowsing(int postId, int userId) {
        // 对应贴子的浏览数 +1
        Post post = postDao.findPostById(postId);
        post.setPostBrowsing(post.getPostBrowsing() + 1);
        System.out.println("更新后的贴子：" + post);
        postDao.updatePost(post);

        // 先删除掉用户之前反问此贴子的历史浏览记录
        postBrowsingDao.deleteUserBrowsingByPostId(userId, postId);
        // 贴子浏览记录增加，并返回新的浏览记录实体
        int id = postBrowsingDao.createPostBrowsing(new PostBrowsing(postId, userId));
        return postBrowsingDao.findPostBrowsingById(id);
    }

    @Override
    public boolean deleteUserBrowsing(int userId) {
        return postBrowsingDao.deleteUserBrowsing(userId);
    }

    /**
     * 判断该用户是否已经点赞过这个贴子
     * 如果已经点赞过了，则为取消点赞操作，如果没有再创建点赞
     * @param postId 受处理的贴子 id
     * @param userId 处理的用户 id
     * @return 新点赞的实例对象，取消点赞则返回 null
     */
    @Override
    public PostLiked changePostLiked(Integer postId, Integer userId) {
        // 找到对应的贴子和点赞对象
        Post post = postDao.findPostById(postId);
        PostLiked postLiked = postLikedDao.findPostLiked(postId, userId);

        // 判断是否已经点过赞
        if(postLiked != null) {
            // 不为空的话取消点赞
            // 点赞记录取消
            postLikedDao.cancelPostLiked(postLiked);

            // 对应贴子点赞数 -1
            post.setPostLiked(post.getPostLiked() - 1);
            postDao.updatePost(post);
            return null;
        }else{
            // 为空的话则新建点赞（新建点赞记录， 对应事件点赞数 +1）

            // 新建点赞记录，并重新从数据库获取到详细内容（创建日期）
            int postLikeId = postLikedDao.createPostLiked(new PostLiked(postId, userId));
            postLiked = postLikedDao.findPostLikedById(postLikeId);

            // 对应贴子点赞数 +1
            post.setPostLiked(post.getPostLiked() + 1);
            postDao.updatePost(post);

            return postLiked;
        }
    }

    @Override
    public boolean isUserLiked(Integer postId, Integer userId) {
        return postLikedDao.findPostLiked(postId, userId) != null;
    }

    /**
     * 判断该用户是否已经收藏过这个贴子
     * 如果已经收藏过了，则为取消收藏操作，如果没有再创建收藏
     * @param postId 受处理的贴子 id
     * @param userId 处理的用户 id
     * @return 新收藏的实例对象，取消收藏则返回 null
     */
    @Override
    public PostCollected changePostCollected(Integer postId, Integer userId) {
        // 找到对应的贴子和收藏对象
        Post post = postDao.findPostById(postId);
        PostCollected postCollected = postCollectedDao.findPostCollected(postId, userId);

        // 判断是否已经收藏过
        if(postCollected != null) {
            // 不为空的话取消收藏
            // 收藏记录取消
            postCollectedDao.cancelPostCollected(postCollected);

            // 对应贴子收藏数 -1
            post.setPostCollected(post.getPostCollected() - 1);
            postDao.updatePost(post);
            return null;
        }else{
            // 为空的话则新建收藏
            // 新建收藏记录，并重新从数据库获取到详细内容（创建日期）
            int postCollectedId = postCollectedDao.createPostCollected(new PostCollected(postId, userId));
            postCollected = postCollectedDao.findPostCollectedById(postCollectedId);

            // 对应贴子收藏数 +1
            post.setPostCollected(post.getPostCollected() + 1);
            postDao.updatePost(post);
            return postCollected;
        }
    }

    @Override
    public boolean isUserCollected(Integer postId, Integer userId) {
        return postCollectedDao.findPostCollected(postId, userId) != null;
    }
}
